# __05__fastapi_serve.py
from fastapi import FastAPI, Request
from fastapi.responses import HTMLResponse
import time
import pickle
from __04__rf_predict_func import predict_func
from __00__config import Config
import uvicorn
import json

app = FastAPI(title="医疗文本分类预测")

# 初始化配置和模型（在应用启动时加载）
config = Config()

# 读取本地模型
with open(config.rf_model_save_path, 'rb') as f:
    model = pickle.load(f)

# 读取本地词向量器
with open(config.tfidf_model_save_path, 'rb') as f:
    tfidf = pickle.load(f)

# 修改 predict_func 中的全局变量
import __04__rf_predict_func
__04__rf_predict_func.model = model
__04__rf_predict_func.tfidf = tfidf
__04__rf_predict_func.config = config

@app.get("/", response_class=HTMLResponse)
async def read_root():
    return """
    <!DOCTYPE html>
    <html lang="zh-CN">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>小医仙 - 智能医疗助手</title>
        <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css">
        <style>
            * {
                margin: 0;
                padding: 0;
                box-sizing: border-box;
            }
            
            body {
                font-family: 'PingFang SC', 'Microsoft YaHei', sans-serif;
                background: linear-gradient(135deg, #ff9a9e 0%, #fad0c4 100%);
                min-height: 100vh;
                padding: 20px;
            }
            
            .container {
                max-width: 800px;
                margin: 0 auto;
                background: rgba(255, 255, 255, 0.95);
                border-radius: 25px;
                padding: 40px;
                box-shadow: 0 15px 35px rgba(0, 0, 0, 0.1);
                backdrop-filter: blur(10px);
                border: 1px solid rgba(255, 255, 255, 0.3);
            }
            
            .header {
                text-align: center;
                margin-bottom: 30px;
            }
            
            .header h1 {
                color: #ff6b9d;
                font-size: 2.8em;
                margin-bottom: 15px;
                text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.1);
            }
            
            .header p {
                color: #666;
                font-size: 1.2em;
            }
            
            .emoji-header {
                font-size: 3em;
                margin-bottom: 20px;
                animation: float 3s ease-in-out infinite;
            }
            
            @keyframes float {
                0% { transform: translateY(0px); }
                50% { transform: translateY(-10px); }
                100% { transform: translateY(0px); }
            }
            
            .input-section {
                background: linear-gradient(45deg, #a8e6cf, #dcedc1);
                border-radius: 20px;
                padding: 30px;
                margin-bottom: 30px;
                box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1);
            }
            
            .input-section h2 {
                color: #5d4037;
                margin-bottom: 20px;
                text-align: center;
                font-size: 1.5em;
            }
            
            textarea {
                width: 100%;
                height: 150px;
                padding: 20px;
                border: 3px solid #ffb6c1;
                border-radius: 15px;
                font-size: 16px;
                resize: vertical;
                background: rgba(255, 255, 255, 0.9);
                font-family: inherit;
                transition: all 0.3s ease;
            }
            
            textarea:focus {
                outline: none;
                border-color: #ff6b9d;
                box-shadow: 0 0 15px rgba(255, 107, 157, 0.3);
            }
            
            .predict-btn {
                display: block;
                width: 100%;
                padding: 18px;
                background: linear-gradient(45deg, #ff6b9d, #ff8e53);
                color: white;
                border: none;
                border-radius: 50px;
                font-size: 1.3em;
                font-weight: bold;
                cursor: pointer;
                margin-top: 20px;
                transition: all 0.3s ease;
                box-shadow: 0 5px 20px rgba(255, 107, 157, 0.4);
            }
            
            .predict-btn:hover {
                transform: translateY(-3px);
                box-shadow: 0 8px 25px rgba(255, 107, 157, 0.6);
            }
            
            .predict-btn:active {
                transform: translateY(1px);
            }
            
            .result-section {
                background: linear-gradient(45deg, #ffd166, #ffb347);
                border-radius: 20px;
                padding: 30px;
                text-align: center;
                display: none;
                box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1);
            }
            
            .result-section h2 {
                color: #5d4037;
                margin-bottom: 20px;
                font-size: 1.5em;
            }
            
            .prediction-result {
                font-size: 2.5em;
                font-weight: bold;
                color: #e91e63;
                margin: 20px 0;
                text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.1);
            }
            
            .response-time {
                font-size: 1.1em;
                color: #5d4037;
                background: rgba(255, 255, 255, 0.7);
                padding: 10px 20px;
                border-radius: 25px;
                display: inline-block;
                margin-top: 15px;
            }
            
            .category-emoji {
                font-size: 3em;
                margin: 15px 0;
            }
            
            .loading {
                display: none;
                text-align: center;
                margin: 20px 0;
            }
            
            .loading-spinner {
                border: 5px solid #f3f3f3;
                border-top: 5px solid #ff6b9d;
                border-radius: 50%;
                width: 50px;
                height: 50px;
                animation: spin 1s linear infinite;
                margin: 0 auto;
            }
            
            @keyframes spin {
                0% { transform: rotate(0deg); }
                100% { transform: rotate(360deg); }
            }
            
            .footer {
                text-align: center;
                margin-top: 30px;
                color: #666;
                font-size: 0.9em;
            }
            
            @media (max-width: 768px) {
                .container {
                    padding: 20px;
                    margin: 10px;
                }
                
                .header h1 {
                    font-size: 2em;
                }
                
                .prediction-result {
                    font-size: 2em;
                }
            }
        </style>
    </head>
    <body>
        <div class="container">
            <div class="header">
                <div class="emoji-header">👩‍⚕️✨</div>
                <h1>小医仙 - 智能医疗助手</h1>
                <p>告诉我你的症状，我来帮你分析应该看哪个科室</p>
            </div>
            
            <div class="input-section">
                <h2>🩺 描述你的症状</h2>
                <textarea id="questionInput" placeholder="例如：我最近总是有很多的白带不知道是为什么请问女性白带增多的原因都有哪些呢？"></textarea>
                <button class="predict-btn" onclick="predict()">
                    <i class="fas fa-stethoscope"></i> 开始智能分析
                </button>
            </div>
            
            <div class="loading" id="loading">
                <div class="loading-spinner"></div>
                <p>小医仙正在认真分析中...</p>
            </div>
            
            <div class="result-section" id="resultSection">
                <h2>🎯 分析结果</h2>
                <div class="category-emoji" id="categoryEmoji">🏥</div>
                <div class="prediction-result" id="predictionResult">-</div>
                <div class="response-time" id="responseTime">⏱️ 响应时间: - ms</div>
            </div>
            
            <div class="footer">
                <p>💡 温馨提示：此分析仅供参考，具体诊断请咨询专业医生</p>
            </div>
        </div>
        
        <script>
            // 根据不同科室显示不同表情符号
            const categoryEmojis = {
                '妇科': '👩⚕️',
                '内科': '💊',
                '外科': '🔪',
                '儿科': '👶',
                '皮肤科': '🧴',
                '眼科': '👁️',
                '耳鼻喉科': '👂',
                '口腔科': '🦷',
                '骨科': '🦴',
                '神经科': '🧠'
            };
            
            async function predict() {
                const question = document.getElementById('questionInput').value.trim();
                if (!question) {
                    alert('请输入你的症状描述哦！');
                    return;
                }
                
                // 显示加载状态
                document.getElementById('loading').style.display = 'block';
                document.getElementById('resultSection').style.display = 'none';
                
                const startTime = performance.now();
                
                try {
                    const response = await fetch('/predict', {
                        method: 'POST',
                        headers: {'Content-Type': 'text/plain'},
                        body: question
                    });
                    
                    const result = await response.json();
                    const endTime = performance.now();
                    const responseTime = (endTime - startTime).toFixed(2);
                    
                    // 设置预测结果
                    document.getElementById('predictionResult').textContent = result.prediction;
                    
                    // 设置响应时间
                    document.getElementById('responseTime').textContent = `⏱️ 响应时间: ${responseTime} ms`;
                    
                    // 设置科室对应的表情符号
                    const emoji = categoryEmojis[result.prediction] || '🏥';
                    document.getElementById('categoryEmoji').textContent = emoji;
                    
                    // 隐藏加载状态，显示结果
                    document.getElementById('loading').style.display = 'none';
                    document.getElementById('resultSection').style.display = 'block';
                    
                } catch (error) {
                    document.getElementById('loading').style.display = 'none';
                    alert('预测出错啦: ' + error.message);
                }
            }
            
            // 支持Ctrl+Enter快捷提交
            document.getElementById('questionInput').addEventListener('keydown', function(e) {
                if (e.key === 'Enter' && e.ctrlKey) {
                    predict();
                }
            });
        </script>
    </body>
    </html>
    """

@app.post("/predict")
async def predict_endpoint(request: Request):
    start_time = time.time()

    # 直接获取文本内容
    question_text = await request.body()
    question_text = question_text.decode('utf-8')

    # 构造数据格式
    data = {'questions': question_text}

    # 调用预测函数
    result = predict_func(data)

    # 计算响应时间
    response_time = (time.time() - start_time) * 1000

    # 返回JSON格式结果
    return {
        "prediction": result['pred_class'],
        "response_time": round(response_time, 2)
    }

if __name__ == "__main__":
    uvicorn.run(app, host="127.0.0.1", port=8000)
